package com.cmwa.solution.business.myHome.todo.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonParser.Feature;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.stereotype.Service;

import com.cmwa.solution.base.entity.Employee;
import com.cmwa.solution.base.entity.Page;
import com.cmwa.solution.base.entity.Result;
import com.cmwa.solution.base.entity.SearchParam;
import com.cmwa.solution.business.customerEquity.estimate.dao.EstimateInfoDao;
import com.cmwa.solution.business.myHome.todo.dao.TodoBizRelDao;
import com.cmwa.solution.business.myHome.todo.dao.TodoDao;
import com.cmwa.solution.business.myHome.todo.entity.OverviewData;
import com.cmwa.solution.business.myHome.todo.entity.TodoBizRelVo;
import com.cmwa.solution.business.myHome.todo.entity.TodoVo;
import com.cmwa.solution.business.myHome.todo.enums.ServiceType;
import com.cmwa.solution.business.myHome.todo.service.TodoBizRelGenerateFactory;
import com.cmwa.solution.business.myHome.todo.service.TodoBizRelGenerator;
import com.cmwa.solution.business.myHome.todo.service.TodoService;
import com.cmwa.solution.business.postMaintenance.dao.PostPersonnelInfoDao;
import com.cmwa.solution.business.postMaintenance.entity.PostPersonnelInfoVo;
import com.cmwa.solution.exception.ValidateFailedException;
import com.cmwa.solution.sys.attach.dao.AttachDao;
import com.cmwa.solution.sys.attach.dao.AttachRelExtDao;
import com.cmwa.solution.sys.attach.entity.AttachRelExtVo;
import com.cmwa.solution.sys.dictionary.entity.DictionaryVo;
import com.cmwa.solution.sys.opinion.entity.HistoryOpinionVo;
import com.cmwa.solution.sys.opinion.enums.HisActionTyps;
import com.cmwa.solution.sys.opinion.enums.HisType;
import com.cmwa.solution.sys.opinion.service.HistoryOpinionService;
import com.cmwa.solution.utils.Constant;
import com.cmwa.solution.utils.SessionUtils;
import com.cmwa.solution.utils.cached.DictionaryCached;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;

/**
 * 待办表业务实现层
 * 
 * @author ex-zuotc
 * @date 2019-01-30 18:23:07
 */
@Service
public class TodoServiceImpl implements TodoService {
	@Resource
	private TodoDao todoDao;
	@Resource
	private AttachDao attachDao;
	@Resource
	private AttachRelExtDao attachRelExtDao;
	@Resource
	private EstimateInfoDao estimateInfoDao;
	@Resource
	private HistoryOpinionService historyOpinionService;
	@Resource
	private TodoBizRelDao todoBizRelDao;
	@Resource
	private PostPersonnelInfoDao postPersonnelInfoDao;

	@Override
	public void insertTodo(TodoVo todo) {
		todoDao.insertTodo(todo);
	}

	@Override
	public void physicDeleteTodoById(String id) {
		todoDao.physicDeleteTodoById(id);
	}

	@Override
	public void logicDeleteTodoById(String id) {
		todoDao.logicDeleteTodoById(id);
	}

	@Override
	public void updateTodoById(TodoVo todo) {
		todoDao.updateTodoById(todo);
	}

	@Override
	public Page<TodoVo> todoListPage(SearchParam sp) {
		Employee employee = SessionUtils.getEmployee();
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			sp.getSp().put("company", employee.getCompany());
		}

		List<TodoVo> items = todoDao.todoListPage(sp);
		return Page.create(items, sp.getStart(), sp.getLimit(), sp.getTotal());
	}

	@Override
	public List<TodoVo> listAllTodo() {
		Employee employee = SessionUtils.getEmployee();
		String company = "";
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			company = employee.getCompany();
		}

		List<TodoVo> items = todoDao.listAllTodo(company);
		
		return items;
	}

	@Override
	public TodoVo getTodoById(String id) {

		TodoVo todoVo = todoDao.getTodoById(id);
		String postCode = DictionaryCached.getDictName("POST_BY_SERVICE", "POST_BY_SERVICE", "POST_BY_SERVICE",
				todoVo.getServiceType());
		String resourceId = "";

		if (StringUtils.equals(todoVo.getServiceType(), ServiceType.INFO_DIS_REGULATORY.name())) {
			resourceId = todoVo.getManageCompany();
		} else {
			resourceId = todoVo.getPrjCode();
		}

		List<PostPersonnelInfoVo> personnelInfoList = postPersonnelInfoDao.queryPersonnelInfoList(postCode, resourceId);
		if (CollectionUtils.isNotEmpty(personnelInfoList)) {
			todoVo.setPostPersonnelId(personnelInfoList.get(0).getPersonnelId());
		}
		;

		return todoVo;
	}

	@Override
	public List<OverviewData> getOverviewData() {
		String currentUserId = SessionUtils.getEmployee().getID();
		String company = null;
		Employee employee = SessionUtils.getEmployee();
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			company = employee.getCompany();
		}

		// 查询待办
		List<TodoVo> overviewList = todoDao.queryOverviewList(currentUserId, company);
		List<PostPersonnelInfoVo> personnelInfoList = postPersonnelInfoDao.queryPersonnelInfoList(null, null);
		Map<String, String> personnelInfoMap = new HashMap<>();
		personnelInfoList.forEach(vo -> {
			personnelInfoMap.put(vo.getResourceId() + vo.getPostCode(), vo.getPersonnelId());
		});

		Map<String, OverviewData> overviewDates = new HashMap<>();

		// 查询数据字典
		String dctType = "SERVICE_TYPE";
		List<DictionaryVo> dctTypes = DictionaryCached.getDictionaryByType(dctType);
		Map<String, DictionaryVo> dctMap = new HashMap<String, DictionaryVo>();
		dctTypes.forEach(dct -> {
			dctMap.put(dct.getDctValue(), dct);
			OverviewData e = new OverviewData();
			e.setServiceType(dct.getDctValue());
			overviewDates.put(dct.getDctValue(), e);
		});

		for (int i = 0; i < overviewList.size(); i++) {
			TodoVo todoVo = overviewList.get(i);
			OverviewData overviewData = overviewDates.get(todoVo.getServiceType());
			if (overviewData != null) {

				String postCode = DictionaryCached.getDictName("POST_BY_SERVICE", "POST_BY_SERVICE", "POST_BY_SERVICE",
						todoVo.getServiceType());
				if (StringUtils.equals(todoVo.getServiceType(), ServiceType.INFO_DIS_REGULATORY.name())) {
					todoVo.setPostPersonnelId(personnelInfoMap.get(todoVo.getManageCompany() + postCode));
				} else {
					todoVo.setPostPersonnelId(personnelInfoMap.get(todoVo.getPrjCode() + postCode));
				}

				if (StringUtils.equals(todoVo.getStatus(), "I") || StringUtils.equals(todoVo.getStatus(), "R")) {
					// 材料待上传
					overviewData.getToUploadList().add(todoVo);
				} else if (StringUtils.equals(todoVo.getStatus(), "S")) {
					// 材料待确认
					overviewData.getToConfirmList().add(todoVo);
				} else if (StringUtils.equals(todoVo.getStatus(), "C")) {
					// 处理中
					overviewData.getToProcessList().add(todoVo);
				} else if (StringUtils.equals(todoVo.getStatus(), "E")) {
					// 已完成
					overviewData.getComplateList().add(todoVo);
				}
			}
		}

		List<OverviewData> result = Lists.newArrayList(overviewDates.values());

		// 按数据字典的顺序排序
		result.sort(
				(OverviewData d1, OverviewData d2) -> Integer.valueOf(dctMap.get(d1.getServiceType()).getDctSortNo())
						.compareTo(Integer.valueOf(dctMap.get(d2.getServiceType()).getDctSortNo())));

		return result;
	}

	/**
	 * 校验
	 * 
	 * @param todoId
	 */
	@Override
	public void checkTodoStatus(String todoId, String operType) {
		if (StringUtils.isNotEmpty(todoId)) {
			TodoVo todoVo = todoDao.getTodoById(todoId);
			if (todoVo == null) {
				throw new ValidateFailedException("数据不存在或已被删除。");
			}

			switch (operType) {
			case "fileUpload":
				if (!StringUtils.equals(todoVo.getStatus(), "I") && !StringUtils.equals(todoVo.getStatus(), "R")) {
					throw new ValidateFailedException("材料已上传，无需重复上传。");
				}
				break;
			case "fileConfirm":
				if (!StringUtils.equals(todoVo.getStatus(), "S")) {
					throw new ValidateFailedException("材料未上传或已确认，不能确认。");
				}
				break;
			case "fileEnd":
				if (!StringUtils.equals(todoVo.getStatus(), "C")) {
					throw new ValidateFailedException("材料未确认，暂不能上传产出报告。");
				}
				break;

			default:
				break;
			}
		}
	}

	@Override
	public void save(TodoVo todoVo, String attIds, String fileEndAttId, String attachJson, String operType,
			String confirmResult, String opinion) {

		String userId = SessionUtils.getEmployee().getID();

		String fileEndRelType = "MY_TODO_FILE_END";
		String relType = "MY_TODO";
		if (StringUtils.equals(operType, "fileUpload") || StringUtils.equals(operType, "add")) {
			// 文件不为空则插入/修改状态为材料已上传
			if (StringUtils.isNotEmpty(attIds)) {
				todoVo.setStatus("S");
				todoVo.setUploader(userId);
				// 有材料上传，标识更新至数据库
				todoVo.setNoFile(Constant.NO);
			} else {
				todoVo.setStatus("I");
			}

			if (StringUtils.equals(operType, "fileUpload")) {
				checkTodoStatus(todoVo.getId(), "fileUpload");

				todoVo.setUploader(userId);
				todoDao.updateTodoById(todoVo);
			} else if (StringUtils.equals(operType, "add")) {

				// 无材料上传
				if (StringUtils.equals(todoVo.getNoFile(), Constant.YES)) {
					todoVo.setStatus("C");
					todoVo.setConfirmer(userId);
				}
				todoVo.setCreateId(userId);
				todoDao.insertTodo(todoVo);

				// 生成对应模块的业务数据
				TodoBizRelGenerator generator = TodoBizRelGenerateFactory
						.getGenerator(ServiceType.valueOf(todoVo.getServiceType()));
				if (generator != null) {
					generator.generateByTodo(todoVo);
				}
			}

			List<Map<String, String>> files = null;

			List<AttachRelExtVo> list = new ArrayList<AttachRelExtVo>();

			AttachRelExtVo attachRelExtVo = null;

			if (StringUtils.isNotBlank(attachJson)) {
				ObjectMapper objectMapper = new ObjectMapper();
				objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
				try {
					// [{attachId=1623, expandField=fileType, expandValue=, relType=MY_TODO}]
					files = objectMapper.readValue(attachJson, new TypeReference<List<Map<String, String>>>() {
					});
					String attId = null;
					// String extId = null;
					String relId = todoVo.getId();
					String attrName = null;
					String attrValue = null;
					attachRelExtDao.deleteAttachRelAndExt(relType, relId);
					for (Map<String, String> map : files) {
						attId = map.get("attachId");
						// extId = map.get("extId");
						relType = map.get("relType");
						attrName = map.get("expandField");
						attrValue = map.get("expandValue");
						attachRelExtVo = new AttachRelExtVo(null, null, attrName, attrValue, null, userId, null, null,
								null, attId, relId, relType);

						list.add(attachRelExtVo);
					}

					if (CollectionUtils.isNotEmpty(list)) {
						attachRelExtDao.batchInsertAttachRelAndExt(list);
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else if (StringUtils.equals(operType, "fileConfirm")) {
			checkTodoStatus(todoVo.getId(), "fileConfirm");

			todoVo.setUploader(null);
			todoVo.setConfirmer(userId);
			todoVo.setStatus(confirmResult);
			todoDao.updateTodoById(todoVo);

			// 保存审批意见
			HistoryOpinionVo historyOpinionVo = new HistoryOpinionVo();
			historyOpinionVo.setHisType(HisType.MY_TODO);
			historyOpinionVo.setSourceId(todoVo.getId());
			historyOpinionVo.setHisAction(HisActionTyps.C);
			historyOpinionVo.setCreateId(userId);
			historyOpinionVo.setHisOpinion(opinion);
			historyOpinionService.addHistoryOpinionInfo(historyOpinionVo);
		} else if (StringUtils.equals(operType, "fileEnd")) {
			checkTodoStatus(todoVo.getId(), "fileEnd");

			if (StringUtils.equals(confirmResult, "E")) {
				todoVo.setEndId(userId);
				todoVo.setStatus(confirmResult);
				todoDao.updateTodoById(todoVo);
			}

			if (StringUtils.isNotEmpty(fileEndAttId)) {
				attachDao.deleteAttachRel2(todoVo.getId(), fileEndRelType);
				attachDao.addAttachRel2(userId, todoVo.getId(), fileEndRelType, fileEndAttId);
			}
		}
	}

	/**
	 * 新增估值表
	 */
	@SuppressWarnings("unused")
	private void addEstiMate(TodoVo todoVo) {
		/*
		 * EstimateInfoVo estimateInfo = new EstimateInfoVo(); String empId =
		 * SessionUtils.getEmployee().getID();
		 * //estimateInfo.setReportType(todoVo.getTodoType());//报告类型 Date todoDate =
		 * todoVo.getTodoDate(); SimpleDateFormat sdf = new
		 * SimpleDateFormat("yyyyMMdd"); String date = sdf.format(todoDate);
		 * estimateInfo.setReportTime(date);//报告日期
		 * //estimateInfo.setPrjCode(todoVo.getPrdCode());//产品编码
		 * estimateInfo.setCreateId(empId); estimateInfo.setStatus("S");
		 * estimateInfoDao.insertEstimateInfo(estimateInfo);
		 */
	}

	@Override
	public List<TodoVo> queryList(TodoVo todoVo) {
		return todoDao.queryList(todoVo);
	}

	@Override
	public List<TodoVo> queryTodoOutFiles(String ids) {
		return todoDao.queryTodoOutFiles(ids);
	}

	@Override
	public Page<TodoVo> toUploadListPage(SearchParam sp) {
		Employee employee = SessionUtils.getEmployee();
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			sp.getSp().put("company", employee.getCompany());
		}

		List<TodoVo> items = todoDao.toUploadListPage(sp);
		return Page.create(items, sp.getStart(), sp.getLimit(), sp.getTotal());
	}

	@Override
	public void noFileUpload(String id) {
		String queryRejectInputFiles = Constant.YES;
		List<TodoVo> todoVos = todoDao.queryTodoInputFiles(id, queryRejectInputFiles);
		String noFile = null;
		if (CollectionUtils.isNotEmpty(todoVos)) {
			noFile = Constant.NO;
		} else {
			noFile = Constant.YES;
		}
		todoDao.noFileUpload(id, noFile);
	}

	@Override
	public int queryTodoCount() {

		Employee employee = SessionUtils.getEmployee();
		String company = null;
		if (StringUtils.equals(employee.getEmpType(), "OUT")) {
			company = employee.getCompany();
		}
		return todoDao.queryTodoCount(company);
	}

	@Override
	public List<TodoBizRelVo> queryRelVoByBiz(String bizType, String bizId) {
		List<TodoBizRelVo> bizRelVo = todoBizRelDao.queryByBiz(bizType, bizId);
		return bizRelVo;
	}

	@Override
	public List<TodoVo> queryTodoInputFiles(String ids) {
		return todoDao.queryTodoInputFiles(ids, null);
	}

	@Override
	public Result<Object> validateExistsFile(String bizType, String bizId, String fileType) {
		Result<Object> result = new Result<>(false);

		if (StringUtils.isNotEmpty(bizType) && StringUtils.isNotEmpty(bizId) && StringUtils.isNotEmpty(fileType)) {
			List<TodoBizRelVo> relVos = queryRelVoByBiz(bizType, bizId);
			if (CollectionUtils.isNotEmpty(relVos)) {
				List<String> idList = new ArrayList<>();
				for (TodoBizRelVo relVo : relVos) {
					idList.add(relVo.getTodoId());
				}
				String ids = Joiner.on(",").join(idList);

				List<TodoVo> todoVos = null;
				if (StringUtils.equals(fileType, "input")) {
					todoVos = queryTodoInputFiles(ids);
				} else if (StringUtils.equals(fileType, "output")) {
					todoVos = queryTodoOutFiles(ids);
				}

				if (CollectionUtils.isNotEmpty(todoVos)) {
					result.setSuccess(true);
				}
			}
		}
		return result;
	}

	@Override
	public void deleteTodo(String id) {
		TodoVo todoVo = todoDao.getTodoById(id);
		if (todoVo != null) {
			todoDao.logicDeleteTodoById(id);

			// 删除对应模块的业务数据
			TodoBizRelGenerator generator = TodoBizRelGenerateFactory
					.getGenerator(ServiceType.valueOf(todoVo.getServiceType()));
			if (generator != null) {
				generator.deleteByTodo(todoVo);
			}
		}
	}

}
